package com.czb.czbmybatis.sqlsession;

import com.czb.czbmybatis.config.Function;
import com.czb.czbmybatis.config.MapperBean;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;

/**
 * @author: 陈正彬
 * 动态代理生成Mapper对象，调用HspExecutor方法
 */
public class CzbMapperProxy implements InvocationHandler {
    private CzbSqlSession czbSqlSession;
    private String mapperFile;
    private CzbConfiguration czbConfiguration;

    //构造器
    public CzbMapperProxy(CzbSqlSession czbSqlSession, Class clazz,
                          CzbConfiguration czbConfiguration) {
        this.czbSqlSession = czbSqlSession;
        this.mapperFile = clazz.getSimpleName() + ".xml";
        this.czbConfiguration = czbConfiguration;
    }

    //当执行Mapper接口的代理对象方法时，会执行到invoke方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MapperBean mapperBean = czbConfiguration.readMapper(this.mapperFile);
        //判断方法所在接口的名字是否和xml文件对应的接口相同
        if (!method.getDeclaringClass().equals(mapperBean.getInterfaceName())) {
            return null;
        }
        //取出mapperBean的function
        List<Function> functions = mapperBean.getFunctions();
        if (null != functions && 0 != functions.size()) {
            for (Function function : functions) {

                //当前要执行的方法和function.getFunName()一样
                //说明可以从当前遍历的function对象中，取出相应的信息（sql），并执行
                if (method.getName().equals(function.getFunName())) {
                    //如果当前的function要执行的sqlType是select
                    //我们就去执行selectOne
                    /*
                    因为我这里主要是写mybatis生成mapper动态代理对象，调用方法的机制，所以做了简化只写了selectOne
                    实际上CzbSqlSession应该对应多个方法，根据不同的情况调用不同的方法，并且还需要进行
                    参数解析处理，还要比较复杂的字符串处理，拼接sql 等
                     */
                    if ("select".equals(function.getSqlType())) {
                        return czbSqlSession.selectOne(function.getSql(),String.valueOf(args[0]));
                    }
                }
            }
        }
        return null;
    }

    //
}
